package cn.tonyandmoney.voicenotes

import android.os.Bundle
import android.support.design.widget.FloatingActionButton
import android.support.v7.widget.LinearLayoutManager
import android.view.Gravity
import android.view.Menu
import android.view.MenuItem
import cn.tonyandmoney.anko.adapter.KAdapter
import cn.tonyandmoney.baidu.ISpeech
import cn.tonyandmoney.baidu.asr.entity.NluResult
import cn.tonyandmoney.baidu.asr.event.AsrResultEvent
import cn.tonyandmoney.baidu.asr.event.AsrStateEvent
import cn.tonyandmoney.baidu.asr.recognizer.RecogResult
import cn.tonyandmoney.baidu.bus.SpeechBus
import cn.tonyandmoney.baidu.consumers.RxConsumer
import cn.tonyandmoney.voicenotes.notes.config.RecogParams
import com.zlzsy.app.base.ui.BaseActivity
import io.reactivex.Observable
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.functions.Consumer
import io.reactivex.schedulers.Schedulers
import org.jetbrains.anko.*
import org.jetbrains.anko.design.floatingActionButton
import org.jetbrains.anko.recyclerview.v7.recyclerView

/**
 * @author niantuo 976045042@qq.com
 * @createdTime 2018/5/21 23:42
 *
 *  语音识别的界面，主要是显示识别的过程以及语音识别启动的过程
 */
class ASRActivity : BaseActivity(), Consumer<AsrResultEvent>, AnkoLogger {

    private val mAdapter = KAdapter<AsrResultEvent>()
    private lateinit var mFloatBtn: FloatingActionButton

    override fun initView() {
        frameLayout {
            padding = dip(10)
            recyclerView {
                layoutManager = LinearLayoutManager(ctx)
                mAdapter.bindToRecyclerView(this)
            }.lparams(matchParent, matchParent)

            floatingActionButton {
                mFloatBtn = this
                imageResource = R.drawable.ic_play_circle_filled_black_24dp
                setOnClickListener { startAsr() }
            }.lparams(dip(45), dip(45)) {
                gravity = Gravity.BOTTOM or Gravity.END
            }
        }

        supportActionBar?.setDisplayHomeAsUpEnabled(true)

        mAdapter.setItemView {
            verticalLayout {
                textView {
                    id = R.id.asr_result
                    backgroundResource = android.R.color.white
                    topPadding = dip(10)
                    leftPadding = dip(10)
                    rightPadding = dip(10)
                    textSize = 15f
                }
                textView {
                    id = R.id.asr_nlu_result
                    backgroundResource = android.R.color.white
                    padding = dip(10)
                    textSize = 13f
                }
                bottomPadding = dip(10)
                lparams(matchParent, wrapContent)
            }
        }.setDataBind { holder, event ->
            if (event.code == AsrResultEvent.CODE_FINAL || event.code == AsrResultEvent.CODE_PARTIAL) {
                holder.setText(R.id.asr_result, "语音识别：" + event.result.bestResult)
                holder.setVisible(R.id.asr_result, true)
                val nluResult = event.nluResult
                if (nluResult.hasNluResult()) {
                    holder.setText(R.id.asr_nlu_result, "语义识别：" + event.nluResult.intent + "_" + event.nluResult.domain)
                } else {
                    holder.setText(R.id.asr_nlu_result, "语义识别：无")
                }
            } else if (event.code == AsrResultEvent.CODE_STATE) {
                holder.setVisible(R.id.asr_result, false)
                holder.setText(R.id.asr_nlu_result, "引擎状态：${event.results!![0]}")
            }
        }

    }

    override fun initData(savedInstanceState: Bundle?) {
        SpeechBus.register<AsrResultEvent>()
                .filter { !it.result.bestResult.isNullOrBlank() }
                .subscribeOn(Schedulers.computation())
                .unsubscribeOn(Schedulers.computation())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(RxConsumer(this))

        SpeechBus.register<AsrStateEvent>()
                .subscribeOn(Schedulers.computation())
                .unsubscribeOn(Schedulers.computation())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(RxConsumer<AsrStateEvent>(Consumer {
                    mAdapter.addData(AsrResultEvent(AsrResultEvent.CODE_STATE, arrayOf(it.desc), RecogResult(), NluResult()))
                    onAsrStateChanged(it)
                }))

        info("asr->" + ISpeech.INSTANCE?.isRecognizing)
        if (ISpeech.INSTANCE == null) {
            mFloatBtn.isEnabled = false
            startAsr()
        } else {
            mFloatBtn.isEnabled = !ISpeech.INSTANCE!!.isRecognizing
            if (!ISpeech.INSTANCE!!.isRecognizing) {
                mAdapter.addData(AsrResultEvent(AsrResultEvent.CODE_STATE, arrayOf("语音识别已停止")))
                ISpeech.INSTANCE!!.destroy()
            } else {
                mAdapter.addData(AsrResultEvent(AsrResultEvent.CODE_STATE, arrayOf("正在识别")))
            }
        }
    }

    private fun startAsr() {
        showLoadingDialog()
        Observable.create<Boolean> { observer ->
            ISpeech.create(this, Consumer {
                observer.onNext(true)
                observer.onComplete()
            }, RecogParams())
        }
                .map {
                    ISpeech.INSTANCE!!.start()
                    true
                }
                .subscribeOn(Schedulers.io())
                .unsubscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(RxConsumer(Consumer {
                    hideLoadingDialog()
                    toast("启动成功")
                }), Consumer {
                    hideLoadingDialog()
                    toast("启动失败。")
                    mFloatBtn.isEnabled = true
                })
    }

    private fun onAsrStateChanged(event: AsrStateEvent) {
        when (event) {
            AsrStateEvent.EXIT -> mFloatBtn.isEnabled = true
            else -> mFloatBtn.isEnabled = false
        }
    }

    override fun accept(t: AsrResultEvent) {
        mAdapter.addData(t)
        mAdapter.moveToLast()
    }

    override fun onCreateOptionsMenu(menu: Menu?): Boolean {
        menuInflater.inflate(R.menu.asr_details_menu, menu)
        return true
    }

    override fun onOptionsItemSelected(item: MenuItem): Boolean {
        if (item.itemId == R.id.action_clear) {
            mAdapter.setNewData(mutableListOf())
            return true
        }
        return super.onOptionsItemSelected(item)
    }
}